package edu.ccut.saturn.component.impl.directory;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import org.apache.commons.io.FileUtils;
import org.osgi.framework.Bundle;

import edu.ccut.saturn.component.IBundleInfo;
import edu.ccut.saturn.component.SaturnComponentException;

/**
 * 页面组件文件夹路径资源的实现类，页面组件文件夹位于bundle的根路径或模块类型文件夹内部，并且页面组件文件内部可以嵌套页面组件文件夹。
 * 页面组件文件夹用于保存页面文件。目前支持页面文件的类型是jsp文件。通过加载方法可以将bundle的jar包中的页面文件发布到web根路径下。
 * <p><code>SaturnWebDirectoryInfo</code>扩展了类<code>AbstractDirectoryInfo</code>。
 * 
 * @author 谷钰
 * @author 温建
 * 
 * @version 1.0 2008.8.29
 * 
 * @see AbstractDirectoryInfo
 * @see IBundleInfo
 * 
 */
//TODO:bad code
public class SaturnWebDirectoryInfo extends AbstractDirectoryInfo {

	private boolean isDelete;

	public SaturnWebDirectoryInfo() {
		super(SATURN_DIRECTORY_TYPE_WEB);
		isDelete = true;
	}

	@Override
	public void load(Bundle bundle, IBundleInfo bundleInfo) {

		try {
			this.deploy(bundle, super.getDirectoryPath(), this
					.getWebRootBundleDirectory(bundleInfo.getWebRootPath(),
							bundle.getSymbolicName()));

		} catch (SaturnComponentException e) {
			logger.error(
					"deploy web page failed! the path to be deployed is \""
							+ bundleInfo.getWebRootPath() + "\" in bundle ["
							+ bundle.getSymbolicName() + "]", e);
		}
	}

	@Override
	public void unload(Bundle bundle, IBundleInfo bundleInfo) {

		try {
			this.undeploy(this.getWebRootBundleDirectory(bundleInfo
					.getWebRootPath(), bundle.getSymbolicName()));

		} catch (SaturnComponentException e) {
			logger.error(
					"undeploy web page failed! the path want to be undeployed is \""
							+ bundleInfo.getWebRootPath() + "\" in bundle ["
							+ bundle.getSymbolicName() + "]", e);
		}
	}

	private String getWebRootBundleDirectory(String webRootPath,
			String symbolicName) throws SaturnComponentException {

		if (webRootPath == null || webRootPath.length() == 0) {
			logger.error("Can't find web root path");
			throw new SaturnComponentException("Can't find web root path");
		}

		String webRootBundleDirectory = webRootPath.replace("\\", "/") + "/"
				+ symbolicName;

		return webRootBundleDirectory;
	}

	@SuppressWarnings("unchecked")
	private void deploy(Bundle bundle, String directoryPath,
			String webRootBundlePath) throws SaturnComponentException {

		this.setDelete(false);
		createDirctory(webRootBundlePath);
		this.setDelete(true);
		copyDirectory(bundle, directoryPath, webRootBundlePath);
	}

	private void undeploy(String webRootBundlePath)
			throws SaturnComponentException {

		if (webRootBundlePath != null) {
			File directory = new File(webRootBundlePath);

			try {
				FileUtils.deleteDirectory(directory);

			} catch (IOException e) {
				logger.error("delete direcory failed in [" + directory + "]");
				throw new SaturnComponentException("delete direcory failed in ["
						+ directory + "]");
			}
		}

		// TODO:是否有更好的方案，现在没有删除容器的jsp缓存
	}

	@SuppressWarnings("unchecked")
	private void copyDirectory(Bundle bundle, String directoryPath,
			String copyPath) throws SaturnComponentException {

		createDirctory(copyPath + "/" + directoryPath);
		Enumeration<String> filePaths = bundle.getEntryPaths(directoryPath);

		if (filePaths == null) {
			return;
		}

		while (filePaths.hasMoreElements()) {
			String filePath = filePaths.nextElement();

			if (filePath.endsWith("/")) {
				copyDirectory(bundle, filePath, copyPath);

			} else {
				createFile(bundle, copyPath + "/" + filePath, filePath);
			}
		}
	}

	private void createDirctory(String path) throws SaturnComponentException {
		File directory = new File(path);

		if (directory.exists()) {

			if (isDelete()) {

				try {
					FileUtils.deleteDirectory(directory);

				} catch (IOException e) {
					logger.error("delete direcory failed in [" + path + "]");
					throw new SaturnComponentException(
							"delete direcory failed in [" + path + "]");
				}

				if (!directory.mkdirs()) {
					logger.error("create direcory failed in [" + path + "]");
					throw new SaturnComponentException(
							"create direcory failed in [" + path + "]");
				}
			}

		} else {

			if (!directory.mkdirs()) {
				logger.error("create direcory failed in [" + path + "]");
				throw new SaturnComponentException("create direcory failed in ["
						+ path + "]");
			}
		}
	}

	public boolean isDelete() {
		return isDelete;
	}

	public void setDelete(boolean isDelete) {
		this.isDelete = isDelete;
	}

	private void createFile(Bundle bundle, String copyFilePath, String filePath)
			throws SaturnComponentException {

		try {
			File file = new File(copyFilePath);
			URL url = bundle.getEntry(filePath);
			FileUtils.copyURLToFile(url, file);

		} catch (IOException e) {
			logger.error("create file failed in [" + copyFilePath + "]", e);
			throw new SaturnComponentException("create file failed in ["
					+ copyFilePath + "]");
		}
	}
}
